<template>
  <div ref="outer" class="waterfall-flex" :style="{ gap: `${horizontalGap}px` }">
    <div v-for="c of columnCount" :key="c" class="col" :style="{ gap: `${verticalGap}px` }">
      <div v-for="item in group[c - 1]" :key="item[idKey]" class="cell">
        <slot :item="item" :width="computedColumnWidth"></slot>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
  import { ref, computed, onMounted, watch, onActivated, onBeforeUnmount } from 'vue';

  const props = withDefaults(
    defineProps<{
      items: any[];
      horizontalGap?: number;
      verticalGap?: number;
      idKey?: string;
      marginWidth?: number;
    }>(),
    {
      horizontalGap: 24,
      verticalGap: 32,
      idKey: 'feed_id',
      marginWidth: 184,
    }
  );

  /* ---------- 状态 ---------- */
  const outer = ref<HTMLDivElement>();
  const containerWidth = ref(0);
  const group = ref<any[][]>([]);

  /* 计算列宽 */
  const computedColumnWidth = computed(() => {
    if (!containerWidth.value) return 0;
    return (
      (containerWidth.value - props.horizontalGap * (columnCount.value - 1)) / columnCount.value
    );
  });

  // 根据容器宽度计算列数的断点配置
  const columnCount = computed(() => {
    let newColumnCount = 2; // 默认设为最小列数
    const diff = props.marginWidth;
    if (containerWidth.value < 720 - diff) {
      newColumnCount = 2;
    } else if (containerWidth.value < 1280 - diff) {
      newColumnCount = 3;
    } else if (containerWidth.value < 1440 - diff) {
      newColumnCount = 4;
    } else if (containerWidth.value < 1920 - diff) {
      newColumnCount = 5;
    } else {
      newColumnCount = 6; // 超大屏幕显示6列
    }

    return newColumnCount;
  });

  /* 计算单个项目的高度 */
  const calculateItemHeight = (item: any, columnWidth: number): number => {
    const width = item.thumbnail.width;
    const height = item.thumbnail.height;

    if (width && height) {
      // 根据列宽和图片原始宽高比计算高度
      return (columnWidth * height) / width;
    }

    // 如果没有宽高信息，使用默认高度
    return 300;
  };

  /* 最短列索引 */
  const minIndex = (currentHeights: number[]): number => {
    let idx = 0;
    for (let i = 1; i < currentHeights.length; i++) {
      if (currentHeights[i] < currentHeights[idx]) idx = i;
    }
    return idx;
  };

  /* 更新分组 */
  const updateGroup = () => {
    if (!containerWidth.value) return;
    const col = columnCount.value;
    const buckets: any[][] = Array.from({ length: col }, () => []);

    const tempHeights = Array(col).fill(0);

    // 按最短列策略分配所有项目
    props.items.forEach((item) => {
      const idx = minIndex(tempHeights);
      buckets[idx].push(item);

      // 计算项目高度并累加（包括垂直间距）
      const itemHeight = calculateItemHeight(item, computedColumnWidth.value);
      tempHeights[idx] += itemHeight + props.verticalGap;
    });

    group.value = buckets;
  };

  /* ---------- 容器宽度测量和更新 ---------- */
  const updateContainerWidth = () => {
    if (outer.value) {
      containerWidth.value = outer.value.offsetWidth;
    }
    console.log('temp', containerWidth.value);
  };

  // 防抖函数
  const debounce = (func: Function, wait: number) => {
    let timeout: ReturnType<typeof setTimeout> | null = null;
    return function executedFunction(...args: any[]) {
      const later = () => {
        if (timeout) {
          clearTimeout(timeout);
        }
        func(...args);
      };
      if (timeout) {
        clearTimeout(timeout);
      }
      timeout = setTimeout(later, wait);
    };
  };

  // 创建防抖版本的updateContainerWidth
  const debouncedUpdateContainerWidth = debounce(updateContainerWidth, 200);

  // 监听相关数据变化，触发更新
  watch(
    [() => props.items, columnCount, () => props.horizontalGap, () => props.verticalGap],
    () => {
      updateGroup();
    },
    { immediate: true }
  );

  onMounted(() => {
    setTimeout(() => {
      updateContainerWidth();
      updateGroup();
    }, 0);

    // 添加窗口resize事件监听，使用防抖处理
    window.addEventListener('resize', debouncedUpdateContainerWidth);
  });

  // 组件卸载时清理事件监听
  onBeforeUnmount(() => {
    window.removeEventListener('resize', debouncedUpdateContainerWidth);
  });
</script>

<style lang="scss" scoped>
  .waterfall-flex {
    display: flex;
    width: 100%;
  }
  .col {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
  }
  .cell {
    width: 100%;
  }
</style>
